package com.three.netty.core.router;

import com.three.api.connection.Connection;
import com.three.api.event.RouterChangeEvent;
import com.three.api.router.ClientLocation;
import com.three.api.router.Router;
import com.three.common.router.RemoteRouter;
import com.three.common.router.RemoteRouterManager;
import com.three.event.EventBus;
import com.three.tools.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.three.common.ServerNodes.GS;

/**
 * Created by mathua on 2017/5/25.
 */
public final class RouterCenter {
    public static final Logger LOGGER = LoggerFactory.getLogger(RouterCenter.class);
    public static final RouterCenter I = new RouterCenter();

    private final LocalRouterManager localRouterManager = new LocalRouterManager();
    private final RemoteRouterManager remoteRouterManager = new RemoteRouterManager();
    private final RouterChangeListener routerChangeListener = new RouterChangeListener();

    /**
     * 注册用户和链接
     *
     * @param playerId
     * @param connection
     * @return
     */
    public boolean register(long playerId, Connection connection) {
        ClientLocation location = ClientLocation
                .from(connection)
                .setHost(Utils.getLocalIp())
                .setPort(GS.getPort());

        LocalRouter localRouter = new LocalRouter(connection);
        RemoteRouter remoteRouter = new RemoteRouter(location);

        LocalRouter oldLocalRouter = null;
        RemoteRouter oldRemoteRouter = null;
        try {
            oldLocalRouter = localRouterManager.register(playerId, localRouter);
            oldRemoteRouter = remoteRouterManager.register(playerId, remoteRouter);
        } catch (Exception e) {
            LOGGER.error("register router ex, playerId={}, connection={}", playerId, connection, e);
        }

        if (oldLocalRouter != null) {
            EventBus.I.post(new RouterChangeEvent(playerId, oldLocalRouter));
            LOGGER.info("register router success, find old local router={}, playerId={}", oldLocalRouter, playerId);
        }

        if (oldRemoteRouter != null && oldRemoteRouter.isOnline()) {
            EventBus.I.post(new RouterChangeEvent(playerId, oldRemoteRouter));
            LOGGER.info("register router success, find old remote router={}, playerId={}", oldRemoteRouter, playerId);
        }
        return true;
    }

    public boolean unRegister(long playerId, int clientType) {
        localRouterManager.unRegister(playerId, clientType);
        remoteRouterManager.unRegister(playerId, clientType);
        return true;
    }

    public Router<?> lookup(long playerId, int clientType) {
        LocalRouter local = localRouterManager.lookup(playerId, clientType);
        if (local != null) return local;
        RemoteRouter remote = remoteRouterManager.lookup(playerId, clientType);
        return remote;
    }

    public LocalRouterManager getLocalRouterManager() {
        return localRouterManager;
    }

    public RemoteRouterManager getRemoteRouterManager() {
        return remoteRouterManager;
    }

    public RouterChangeListener getRouterChangeListener() {
        return routerChangeListener;
    }
}
